import os
import tkinter as tk
from tkinter import filedialog, messagebox, ttk
from PIL import Image

# 图像缩放时使用的高质量抗锯齿算法
# Image.ANTIALIAS 在新版 Pillow 中已弃用，建议使用 Resampling.LANCZOS
if hasattr(Image, 'Resampling'):
    RESAMPLE_FILTER = Image.Resampling.LANCZOS
else:
    RESAMPLE_FILTER = Image.ANTIALIAS

TOLERANCE = 0.001

def process_images_in_folder(folder_path, ratio_w, ratio_h, crop_mode):
    """
    处理文件夹内的图片，进行裁切和缩放。
    """
    if not folder_path:
        return

    try:
        target_aspect_ratio = ratio_w / ratio_h
        target_width = ratio_w * 100
        target_height = ratio_h * 100
    except ZeroDivisionError:
        messagebox.showerror("错误", "高度比例不能为 0。")
        return

    processed_count = 0
    skipped_count = 0
    
    try:
        file_list = os.listdir(folder_path)
    except FileNotFoundError:
        messagebox.showerror("错误", f"找不到文件夹: {folder_path}")
        return
        
    for filename in file_list:
        file_path = os.path.join(folder_path, filename)

        if os.path.isfile(file_path) and filename.lower().endswith(('.png', '.jpg', '.jpeg', '.bmp')):
            try:
                with Image.open(file_path) as img:
                    width, height = img.size
                    
                    if height == 0:
                        skipped_count += 1
                        continue

                    current_ratio = width / height
                    
                    # 如果当前比例小于目标比例 (图片更瘦长)，则进行处理
                    if current_ratio < target_aspect_ratio - TOLERANCE:
                        # 1. 裁切 (Crop)
                        # 计算裁切为目标比例所需的新高度
                        new_height = int(width / target_aspect_ratio)
                        
                        # 根据模式定义裁切框 (左, 上, 右, 下)
                        if crop_mode == "top":
                            crop_box = (0, 0, width, new_height)
                        elif crop_mode == "bottom":
                            crop_box = (0, height - new_height, width, height)
                        else:  # "center"
                            top_crop = (height - new_height) // 2
                            crop_box = (0, top_crop, width, top_crop + new_height)
                        
                        cropped_img = img.crop(crop_box)
                        
                        # 2. 缩放 (Resize)
                        # 将裁切好的图片统一缩放到目标像素
                        final_img = cropped_img.resize((target_width, target_height), RESAMPLE_FILTER)
                        
                        # 3. 保存 (Save)
                        save_kwargs = {'quality': 95} if img.format == 'JPEG' else {}
                        final_img.save(file_path, **save_kwargs)
                        
                        processed_count += 1
                        print(f"已处理: {filename} -> {target_width}x{target_height}")
                    else:
                        skipped_count += 1
            except Exception as e:
                print(f"处理文件 {filename} 时出错: {e}")
                skipped_count += 1
                
    messagebox.showinfo("处理完成", f"任务完成！\n\n成功处理 {processed_count} 个图片。\n跳过 {skipped_count} 个不符合条件或处理失败的文件。")

def start_processing():
    """
    获取用户输入，验证后开始处理流程。
    """
    # 1. 验证比例输入
    try:
        ratio_w = float(ratio_w_var.get())
        ratio_h = float(ratio_h_var.get())
        if ratio_w <= 0 or ratio_h <= 0:
            messagebox.showerror("输入错误", "比例的宽和高都必须是大于 0 的整数。")
            return
    except ValueError:
        messagebox.showerror("输入错误", "请输入有效的数字作为比例。")
        return

    # 2. 选择文件夹
    folder_selected = filedialog.askdirectory()
    if not folder_selected:
        return

    # 3. 最终确认
    crop_mode = crop_mode_var.get()
    is_confirmed = messagebox.askokcancel(
        "警告：操作不可逆",
        "此操作将直接修改并覆盖原始图片。\n"
        "请确保您已经备份了重要文件！\n\n"
        f"目标比例: {ratio_w}:{ratio_h}\n"
        f"输出像素: {ratio_w*100}x{ratio_h*100}\n"
        f"裁切模式: {crop_mode.capitalize()}\n\n"
        "是否确认并继续？"
    )
    if is_confirmed:
        process_images_in_folder(folder_selected, ratio_w, ratio_h, crop_mode)

# --- GUI ---
root = tk.Tk()
root.title("纵向裁切工具")
root.geometry("450x300")
root.resizable(False, False)

style = ttk.Style()
style.configure("TLabel", padding=5)
style.configure("TButton", padding=5)
style.configure("TRadiobutton", padding=(10, 5))

main_frame = tk.Frame(root, padx=20, pady=15)
main_frame.pack(expand=True, fill="both")

# --- 1. 比例设置 ---
ratio_frame = ttk.LabelFrame(main_frame, text=" 1. 设置裁切比例 ")
ratio_frame.pack(fill="x", pady=(0, 15))

ratio_w_var = tk.StringVar(value="9")
ratio_h_var = tk.StringVar(value="16")

ratio_inner_frame = tk.Frame(ratio_frame, pady=5)
ratio_inner_frame.pack()

ttk.Label(ratio_inner_frame, text="宽:").pack(side="left")
ttk.Entry(ratio_inner_frame, textvariable=ratio_w_var, width=5).pack(side="left", padx=(0, 10))
ttk.Label(ratio_inner_frame, text="高:").pack(side="left")
ttk.Entry(ratio_inner_frame, textvariable=ratio_h_var, width=5).pack(side="left")

# --- 2. 裁切模式 ---
mode_frame = ttk.LabelFrame(main_frame, text=" 2. 选择裁切模式 ")
mode_frame.pack(fill="x", pady=(0, 15))

crop_mode_var = tk.StringVar(value="center")
modes = [("保留顶部", "top"), ("居中裁切", "center"), ("保留底部", "bottom")]
for text, mode in modes:
    rb = ttk.Radiobutton(mode_frame, text=text, variable=crop_mode_var, value=mode)
    rb.pack(anchor="w", padx=10)

# --- 3. 执行 ---
run_frame = ttk.LabelFrame(main_frame, text=" 3. 开始执行 ")
run_frame.pack(fill="x")

process_button = ttk.Button(run_frame, text="选择文件夹并开始处理", command=start_processing)
process_button.pack(pady=10, padx=10, fill="x")

root.mainloop()